package node;


import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.management.ManagementFactory;
import java.net.InetAddress;
import java.net.Socket;
import task.IQueue;
import task.IQueueProxyFactory;
import task.Task;
import discovery.DiscoveryProxyFactory;
import event.Event;
import fileserver.FileServer;

public class NodeManageWorker implements Runnable{
	protected InetAddress 	discoveryAddress;
	protected int 			discoveryPort;
	protected Event			currentEvent;
	private IQueue			taskQueue;
	private Node 			node;

	
	protected NodeManageWorkerListener workerDelegate;
	
	public NodeManageWorker(Event e, InetAddress discoveryAddress, int discoveryPort, IQueue taskQueue, Node node)
	{
		super();
		this.currentEvent 		= e;
		this.discoveryAddress 	= discoveryAddress;
		this.discoveryPort 		= discoveryPort;
		
		this.workerDelegate 	= null;

		this.taskQueue			= taskQueue;
		this.node = node;

	}
	
	public void setWorkerDelegate(NodeManageWorkerListener delegate)
	{
		this.workerDelegate = delegate;
	}
	
	@Override
	public void run() {
		
		if(currentEvent.getType().equals("shutdown"))
		{
			
			try{
				
				//TODO: gestisco attraverso la mia politica i task rimanenti
				
				//creo il file di configurazione XML salvando lo stato attuale del nodedescriptor
				this.node.nodeConfigurator.writer(NodeDescriptor.getInstance().toHashMap());
				
				//mi cancello dal discovery
				String remoteDiscovery = this.node.nodeConfigurator.get_Discovery_ind() + ":" + String.valueOf(this.node.nodeConfigurator.get_Discovery_port()) + ":UDP";
				//TODO: prendere dal configurator ip port del discovery e passarlo a getProxy
				int status = DiscoveryProxyFactory.getInstance().getProxy(remoteDiscovery).delNode(NodeDescriptor.getInstance());
	
				if(status==0){
					String pid = ManagementFactory.getRuntimeMXBean().getName();
					String cmd = "kill " + pid;
					
					ProcessBuilder pb = new ProcessBuilder("bash", "-c",cmd);
			        Process shell = pb.start();
				}
				else
				{
					System.out.println("Errore nella delete del nodo. Try again.");
				}
			}
			catch(IOException e){
				e.printStackTrace();
			}
	
		}
		else if(currentEvent.getType().equals("result"))
		{
			String temp = currentEvent.getContent();
		
			String[] tokens;
			tokens = temp.split(",");
			
			//IP:PORT:FILENAME
			String[] values = null;
		

				String token = tokens[0];
				values = token.split(":");
			
			
			
			String ip_fs_server = values[0];
			int port_fs_server = Integer.parseInt(values[1]);
			String filename = values[2];
			System.out.println("\n\nSto scaricando il file: " +filename +"\n\n");
			//scarico il file dei risultati
			download_file(filename, ip_fs_server, port_fs_server);
			System.out.println("Downloaded result: " + filename);
		}
		else if(currentEvent.getType().equals("updateconf"))
		{
			String temp = currentEvent.getContent();

			String[] tokens;
			tokens = temp.split(",");
			
			//<key>:<value>,<key>:<value>,.......
			String[] values = null;
			String[] tmp = null;
		System.out.println("VALORE DI TEMP: " +tmp);
		System.out.println("VALORE DI VALUES: " +values);
			for(int i = 0; i<=tokens.length;i++){
				tmp = tokens[i].split(":");
				NodeDescriptor.getInstance().parseKeyValue(tmp[0],tmp[1]);
				System.out.println("Modifiche effettuate con successo");	
			}	
		}
		else if(currentEvent.getType().equals("dequeue"))
		{
			//TODO: prendere dal configurator ip port del discovery e passarlo a getProxy
			//prendo il nodedescriptor in base all'ip del nodo che richiede aiuto.
			NodeDescriptor source_node =  DiscoveryProxyFactory.getInstance().getProxy("UDP").lookup(String.valueOf(currentEvent.getContent()));
			
			String temp_dest = source_node.getIp() + ":" + source_node.getDTS() + ":UDP";
			Task tempTask = IQueueProxyFactory.getInstance().getProxy(temp_dest).dequeue();
			taskQueue.enqueue(tempTask);
		}
	}
	
	/**
	 * Metodo per il download dei file.
	 * 
	 */
	
	public int download_file(String filename, String ip_server, int server_port){
		try{
			long start = System.currentTimeMillis();

			    Socket sock = new Socket(ip_server,server_port);
			    System.out.println("Connecting...");

			    //TODO: inserire invio stringa "download" e ricezione ACK
			    DataOutputStream outToServer = new DataOutputStream(sock.getOutputStream());
			    outToServer.writeBytes(filename + "\n");

			    String[] tokens = new String[1];
			    tokens = filename.split("/");
			    filename = tokens[1];
			    String path = FileServer.download + "/" + filename;
			
			    FileOutputStream fos = new FileOutputStream(new File(path));
			    InputStream in = sock.getInputStream();
			    byte[] data = new byte[1024];
			  
				for(int readNum; (readNum = in.read(data))!=-1;)
				{
					 fos.write(data,0,readNum);
				}
				   
			    long end = System.currentTimeMillis();
			    System.out.println(end-start);
			    fos.close();
			    in.close();
			    sock.close();
			    return 0;
			}
			catch (Exception e) 
			{
				System.out.println(e.getMessage());
				return -1;	
			} 
	}
}
